// Echo4 prints its command-line arguments.
package main

import (
	"flag"
	"fmt"
	"github.com/go-redis/redis"
	`strconv`
	"strings"
	`sync`
)

var bigValue = "123123123123123123123123123123123123123123123123123123123123"
var replaceValue = "121121121121121121121121121121121121121121121121121121121121"

func main() {
	var s = flag.Int("s", 0, "set the start of the range")
	var e = flag.Int("e", 100, "set the end of the range")
	var ip = flag.String("ip", "127.0.0.1", "redis ip address")
	var port = flag.Uint("p", 6379, "redis port")
	var pw = flag.String("pw", "", "redis password")
	var db = flag.Int("db", 1, "redis database")
	var gCount = flag.Int("g", 10, "the goroutine will be created")
	var r = flag.Bool("r", false, "the flag to ctrl whether replace the value")
	flag.Parse()
	var data string
	if *r == true {
		data = replaceValue
	} else {
		data = bigValue
	}

	redisAddress := fmt.Sprintf("%s:%d", *ip, *port)
	fmt.Printf("will content redis: %s\n", redisAddress)
	if err := checkConnect(redisAddress, *pw, *db); err != nil {
		fmt.Println(err)
		return
	}

	wg := &sync.WaitGroup{}
	wg.Add(*gCount)
	fmt.Printf("will send total %d key with %d goroutine\n", *e-*s, *gCount)

	for i := 0; i < *gCount; i++ {
		//client := getRedisClient(redisAddress, *pw, *db)
		start := i + *s
		go sendDataToRedis(wg, start, *e, *gCount, redisAddress, *pw, *db, data)
	}
	wg.Wait()

	//fmt.Println("total cost:", time.Since(start))
}

func sendDataToRedis(wg *sync.WaitGroup, start, end, step int, address string, pw string, db int, data string) {
	client := getRedisClient(address, pw, db)
	defer client.Close()

	for i := start; i < end; i = i + step {
		r := client.Set(strconv.Itoa(i), data, 0)
		if !strings.HasSuffix(r.String(), "OK") {
			fmt.Println("send data wrong, detail:", r)
		}
	}

	wg.Done()
}

func checkConnect(address string, pw string, db int) error {
	client := getRedisClient(address, pw, db)
	defer client.Close()

	_, err := client.Ping().Result()
	if err != nil {
		return err
	}
	return nil
}

func getRedisClient(address string, pw string, db int) *redis.Client {
	redisdb := redis.NewClient(
		&redis.Options{
			Addr:     address,
			Password: pw,
			DB:       db,
		})

	return redisdb
}
